
09.02.2015, 17:27
|
Новичок на форуме
|
|
Регистрация: 09.02.2015
Сообщений: 6
|
|
Ajax запрос в два шага
Всем доброго дня! Помогите пожалуйста новичку. Стоит вот такая задача - нужно прикрутить AJAX поиск по номеру детали на сайт. Загвоздка задачи заключается в том, что сама база находится у поставщика и выборка из нее осуществляется посредством их api.
По порядку:
Форма поиска:
Код:
|
<html>
<head>
<h3>Поиск по номеру детали</h3>
<script src="client/livesearch.js"></script>
<style type="text/css">
#livesearch
{
margin:15px;
width:auto;
}
#txt1
{
margin:0px;
background:#ccc;
padding:5px;">
}
</style>
</head>
<body>
<form>
<input type="text" id="txt1" size="300"
onkeyup="showResult(this.value)">
<div id="livesearch"></div>
</form>
</body>
</html> |
Сам поиск livesearch.js
var xmlHttp;
function showResult(str)
{
if (str.length==0)
{
document.getElementById("livesearch").
innerHTML="";
document.getElementById("livesearch").
style.border="0px";
return;
}
xmlHttp=GetXmlHttpObject()
if (xmlHttp==null)
{
alert ("Browser does not support HTTP Request");
return;
}
var url="client/detail.php";
url=url+"?q="+str;
url=url+"&sid="+Math.random();
xmlHttp.onreadystatechange=stateChanged ;
xmlHttp.open("GET",url,true);
xmlHttp.send(null);
}
function stateChanged()
{
if (xmlHttp.readyState==4 || xmlHttp.readyState=="complete")
{
document.getElementById("livesearch").
innerHTML=xmlHttp.responseText;
document.getElementById("livesearch").
style.border="1px solid #A5ACB2";
}
}
function GetXmlHttpObject()
{
var xmlHttp=null;
try
{
// Firefox, Opera 8.0+, Safari
xmlHttp=new XMLHttpRequest();
}
catch (e)
{
// Internet Explorer
try
{
xmlHttp=new ActiveXObject("Msxml2.XMLHTTP");
}
catch (e)
{
xmlHttp=new ActiveXObject("Microsoft.XMLHTTP");
}
}
return xmlHttp;
}
и сам detail.php который осуществляет запрос к базе поставщика
<?
$nacenka=25;
$login='**********';
$password='**********';
$store=true;
$maxDeliveryDays = 1;
//$detailGroup = 'Original'
$wsdl='http://www.part-kom.ru/webservice/search.php?wsdl';
$number=$_GET['q'];
$client = new SoapClient($wsdl);
$result = $client->getMakersByNumber($login, $password, $number, $store, true,true,true);
echo '<div style="width:1000px; margin:20px auto; ">';
$flag=0;
foreach($result as $marka){
if (strtoupper($marka['name'])==strtoupper($_GET['mod'])){$flag=1; $marka_id=$marka['id'];}
}
if ($_GET['marka_id']){ $flag=1; $marka_id=$_GET['marka_id'];}
if ($flag==0){
if (count($result)>0){
echo 'Пожалуйста уточните производителя </br>';
foreach($result as $marka){
echo '<a href="'.$_SERVER['REQUEST_URI'].'&marka_id='.$marka['id'].'">'.$marka['name'].'</a></br>';
}
} else {
echo 'Извините, по данному запросу ничего не найдено ';
}
}
if ($flag==1){
/// ищем только оригиналы
$result_1 = $client->FindDetail($login, $password, $number, $marka_id, $detailGroup,false,false,true,true,true);
if (count($result_1)>0){
ПОЛНЫЙ ФАЙЛ В ПРИЛОЖЕНИИ !!!!
Простите за простыню, но я из самых начинающих новичков
Теперь о самой задаче: Необходимо осуществить поиск по каталожному номеру детали. Естественно, у производителей нумерация не уникальна и пересекается с другими производителями. Поэтому сначала делается выборка всех производителей, имеющих в каталоге деталь с введенным номером.
За это отвечает getMakersByNumber($login, $password, $number, $store, true,true,true); который возвращает ссылки на конкретные элементы каталога, имеющие конкретный идентификатор $number (каталожный номер) и $marka_id (id производителя запчасти), что позволяет выбрать конкретную запчасть.
После уточнения производителя запчасти, снова обращаемся к сервису парткома используя FindDetail, например так: FindDetail($login, $password, $number, $marka_id, $detailGroup,false,false,true,true,true) и получаем всю информацию о стоимости, наличии и т.д.
Моя загвоздка состоит в том, что без обновления страницы я могу получить только результат работы getMakersByNumber, а вот FindDetail работает - но уже с обновлением страницы, что нарушает общий замысел.
Вопрос: как сделать такой запрос в два шага без обновления страницы? Буду премного благодарен за ответы.
Форма живет на moyvin.ru
Последний раз редактировалось evgeniex, 09.02.2015 в 18:24.
|
|

13.02.2015, 08:01
|
Профессор
|
|
Регистрация: 14.01.2015
Сообщений: 12,989
|
|
>После уточнения производителя запчасти, снова обращаемся к сервису парткома используя FindDetail
Обратились, нашли, вернули. Откуда и по какой причине следует обновление страницы, тем более, что у вас асинхронный диалог?
|
|

13.02.2015, 10:00
|
Новичок на форуме
|
|
Регистрация: 09.02.2015
Сообщений: 6
|
|
Вот как-то так
Асинхронно обработался только запрос к getMakersByNumber и результатом его работы является
echo '<a href="'.$_SERVER['REQUEST_URI'].'&marka_id='.$marka['id'].'">'.$marka['name'].'</a></br>';
Она выводится в div livesearch - и все.
Нигде не сказано как нужно обрабатывать эту ссылку, а она имеет вот такой вид:
http://moyvin.ru/client/detail.php?q=34457&sid=0.39250380732119083&marka_id=740
то есть уже в ней самой содержится GET к findDetail.
Может быть присваивать этим ссылкам класс и на этот класс вешать свой обработчик? Но тогда будет два обработчика в одном div , да и я не знаю как без jQuerry это сделать, а с ним только догадываюсь.
$('.ajaxclass').click(function(){
var url = $(this).attr('href');
$('#target').load(url);
return false;
});
но надо без без jQuerry. Там и так уже на странице налеплена хренова туча и все на разных версиях этой библиотеки.
|
|

13.02.2015, 11:49
|
Профессор
|
|
Регистрация: 14.01.2015
Сообщений: 12,989
|
|
>Асинхронно обработался только запрос к getMakersByNumber
Асинхронным должен быть диалог, что там вернул сервер на первый запрос не столь суть, важно какова реакция на этот ответ клиента.
Выбрасывайте из диалога ссылки, а вместо него возвращайте список, выбор в котором сделает второй асинхронный запрос уже с параметром ID марки, ответ соответственно обработаете.
Нет же у вас перезагрузки, пока вы сами на эту ссылку не "наступите".
PS. Переработайте функцию showResult(str) так, чтобы она принимала ключ-значение, определяя источник запроса клиента, и соответственно делала запрос с соответствующим параметром серверу. То есть в первом случае это поле поиска и его параметры, во тором случае, это список и onchange="showResult(this.name, this.value)"
Последний раз редактировалось laimas, 13.02.2015 в 12:05.
|
|

16.02.2015, 15:07
|
Новичок на форуме
|
|
Регистрация: 09.02.2015
Сообщений: 6
|
|
Спасибо, но это для меня сложновато.
А если сделать вот так?
<div id="livesearch" onclick="showContent(this.value)"{return false}></div>
где showContent - еще один обработчик, правда я не очень представляю, как разобрать полученный url на кусочки и снова передать в detail.php
|
|

16.02.2015, 19:03
|
Профессор
|
|
Регистрация: 14.01.2015
Сообщений: 12,989
|
|
Нет, так конечно не пойдет. Во-первых {return false}, это ничего не значащий мусор, и если бы даже было прописано в положенном месте, в параметрах события, то для div все равно не имело бы значения.
Во-вторых, возвращается набор, и это список, и уж если не выпадающий список, то или нумерованный, или маркированный список, но только не div.
Вот только мудрить с чем-то иным, игнорируя выпадающий список, не стоит. Со списком может возникать лишь одна проблема - если возвращается большой объем марок изделия, то конечно, в длинном списке вряд ли удобно делать выбор. В этом случае может потребоваться и еще один запрос, который будет выводить или фиксированные части этого набора, или выбранные по алфавиту. В общем это уже логика, которая зависит от данные, которых я не знаю.
Если не разбираетесь в JS, то подключите jQuery и используйте его. Использование его не означает наплевать на JS, jQuery не панацея, в сего лишь удобный инструмент, а знание первоисточника желательно всегда. Но что-то написать на jQuery проще, и понять его методы не так сложно.
А в РНР хорошо разбираетесь? Вот простой пример. В нем нет вывода сообщений в случае, если поиск не вернет результата. Как вы это собираетесь выводить, это иной вопрос, и мной опущен. Главное в примере, это первичный запрос поля, которое присутствует всегда, и подгружаемый список, как результат второго запроса к ресурсу.
Второй запрос, то есть марок, в примере, это просто получить из массива по индексу (id) список. Финал диалога, это по id марки, получить описание ее (если у вас уточнение марки, то это надо полагать всего лишь уточнение, а не финал). Фактически же у вас будет три запроса ресурса - первый поиск по id, второй получение марок, третий финальный. Клиент при этом будет запрашивать сервер два раза.
<?
//имитатор результата первого запроса к ресурсу
$a = [
1 => [1=>'Марка 1-1','Марка 1-2','Марка 1-3'],
[4=>'Марка 2-1','Марка 2-2','Марка 2-3'],
[7=>'Марка 3-1','Марка 3-2','Марка 3-3']
];
$b = [
1 => 'Описание марки 1-1',
'Описание марки 1-2',
'Описание марки 1-3',
'Описание марки 2-1',
'Описание марки 2-2',
'Описание марки 2-3',
'Описание марки 3-1',
'Описание марки 3-2',
'Описание марки 3-3'
];
if($_POST) {
if($id = (int)current($_POST)) {
//запрос списка, первый запрос клиента
if(key($_POST)=='a' && array_key_exists($id, $a))
exit('<select id="b" onchange="getBrand(this.id,this.value)"><option value="">Уточните марку...</option>'.
implode(array_map(function($k, $v) {
return '<option value="'.$k.'">'.$v.'</option>';
}, array_keys($a[$id]), $a[$id])).'</select>');
//финал - вывод описания, второй запрос клиента
else if(array_key_exists($id, $b)) exit($b[$id]);
}
}
?>
<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<style>
</style>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
<script>
function getBrand(k, v) {
v *= 1;
if(v) {
$.post(location, k+'='+v, function(d) {
//получили список - добавили его на страницу
if(k=='a') $('#f').find('select').remove().end().append(d);
//иначе результат запроса марки
else $('#d').html(d)
})
} else alert('Значение не выбрано!')
}
</script>
</head>
<body>
<div id="f">
<input id="a" /> <button onclick="getBrand($('#a').attr('id'),$('#a').val())">Search</button>
</div>
<div id="d"></div>
</body>
</html>
Пример простой, думаю разобраться не сложно будет. НУ а "мясо на кости" можно нарастить при желании.
Последний раз редактировалось laimas, 17.02.2015 в 00:19.
|
|

18.02.2015, 03:07
|
Новичок на форуме
|
|
Регистрация: 09.02.2015
Сообщений: 6
|
|
Большое спасибо за Ваше участие! Я обязательно попробую реализовать скрипт предложенным Вами методом. Но голова уже давно думает в другую сторону, поэтому попрошу проконсультировать по моему варианту решения этой задачки:
Что сделано: Ссылка из первого блока поиска теперь выводится вот в таком виде:
echo '<a href="'.$_SERVER['REQUEST_URI'].'&marka_id='.$marka['id'].'"onclick="return OpenAjax()">'.$marka['name'].'</a></br>';
что фактически дает вот такую (или аналогичную) конструкцию
<a href="/client/detail.php?q=545&sid=0.4979946280363947&marka_id=127" onclick="return OpenAjax()">DBA</a>
то есть для этих ссылок свой обработчик OpenAjax()
он мало отличается от первого:
function OpenAjax(link) {
var cont = document.getElementById('content');
var loading = document.getElementById('loading');
cont.innerHTML = loading.innerHTML;
var http = createRequestObject();
if( http )
{
link="client/detail.php?q=657&marka_id=639"
http.open("GET", link, true);
http.onreadystatechange = function ()
{
if(http.readyState == 4)
{
cont.innerHTML = http.responseText;
}
}
http.send(null);
}
else
}
// создание ajax объекта
function createRequestObject()
{
try { return new XMLHttpRequest() }
catch(e)
{
try { return new ActiveXObject('Msxml2.XMLHTTP') }
catch(e)
{
try { return new ActiveXObject('Microsoft.XMLHTTP') }
catch(e) { return null; }
}
}
}
И он даже работает, но с двумя "нюансами" вызванными моей крайней неосведомленностью и методом ненаучного тыка:
1. Сейчас link="client/detail.php?q=657&marka_id=639" - поставил это значение для проверки - будет работать или нет. А еще потому, что не знаю как указать скрипту, что link должен быть равен url той ссылки, на которую нажали. Как это сделать?
2. Скрипт работает - то есть выводит в div с id 'content' содержимое ссылки client/detail.php?q=657&marka_id=639 и браузер, зараза,  тут же осуществляет переход по этой же ссылке. Как запретить браузеру по этой ссылке переходить?
|
|

18.02.2015, 07:51
|
Профессор
|
|
Регистрация: 14.01.2015
Сообщений: 12,989
|
|
Ну а что тут комментировать - плохо. Вот чего бы я вам посоветовал, так это выбросить из своей головы такие крайне необдуманные и расточительные методы программирования, и впредь не думать в "такую сторону".
Вы обязаны не просто плодить на гора функции, а писать код оптимизированный. Представьте что вам надо решить задачу "связанных списков", когда запрос каждого списка возвращает следующий список (видели такое на страницах) и среди этих списков есть такие, вывод опций которых для удобства нужно разбить на части. Если таких списков у вас 5, то с вашим подходом нужно создать 4 + N независимых асинхронных запросов? А если больше, тогда что, завалить клиента кучей кода неоправданного?
Не делайте себе скидок на то, что вы не волшебник и пока только учитесь. Учиться нужно как раз пониманию языка и грамотному и творческому использованию его инструментов. А нагромождать беспорядочно и "а че, работает же", это не программирование, это бардак.
Ваш асинхронный диалог с сервером занимается выполнением одной задачи, и на каком участке пути этой задачи, и что необходимо выполнить на данном участке сервер может знать по параметру запроса. Вы же вместо изменения параметра изменяете логику.
Думайте еще, но в другую сторону.
Что касается ссылок - вы в событие у DIV пытались притулить return false, которое ему как пятая нога, а вот для ссылки, это уже будет информация к действию, вернее бездействию. Но посмотрите еще на свою ссылку и на функцию. Посмотрели? Вопрос - что в этом лишнее?
|
|

19.02.2015, 18:48
|
Новичок на форуме
|
|
Регистрация: 09.02.2015
Сообщений: 6
|
|
Спасибо за подсказку - убрал лишний else теперь код работает. осталось только научиться открывать нужные мне ссылки. Я понимаю что мое исполнение кода далеко не совершенно, и представляет с собой сборную солянку из кусков найденных на различных форумах, но переделать все заново я пока не готов - не тот уровень знаний, я этого не скрываю.
Если есть возможность - помогите
сейчас в detail.php ссылка формируется так:
echo '<a href="'.$_SERVER['REQUEST_URI'].'&marka_id='.$marka['id'].'"onclick="return OpenAjax()">'.$marka['name'].'</a></br>';
как передать эту ссылку в функцию OpenAjax() в качестве link ???
function OpenAjax() {
var cont = document.getElementById('content');
var loading = document.getElementById('loading');
cont.innerHTML = loading.innerHTML;
var http = createRequestObject();
if( http )
{
link="client/detail.php?q=657&marka_id=639"
http.open("GET", link, true);
http.onreadystatechange = function ()
{
if(http.readyState == 4)
{
cont.innerHTML = http.responseText;
}
}
http.send(null);
}
return false
}
// создание ajax объекта
function createRequestObject()
{
try { return new XMLHttpRequest() }
catch(e)
{
try { return new ActiveXObject('Msxml2.XMLHTTP') }
catch(e)
{
try { return new ActiveXObject('Microsoft.XMLHTTP') }
catch(e) { return null; }
}
}
}
когда делаю так:
echo 'onclick="return OpenAjax(<a href="'.$_SERVER['REQUEST_URI'].'&marka_id='.$marka['id'].'">'.$marka['name'].'</a></br>)"'
получаю internal server error 500
Видимо что-то не так в функции OpenAjax() но вот что?
|
|

19.02.2015, 19:23
|
Профессор
|
|
Регистрация: 14.01.2015
Сообщений: 12,989
|
|
когда делаю так:
echo 'onclick="return OpenAjax(<a href="'.$_SERVER['REQUEST_URI'].'&marka_id='.$marka['id'].'">'.$marka['name'].'</a></br>)"'
А вы понимаете что это будет представлять из себя на клиенте? То есть вы функции в качестве аргумента хотите передать тег со всеми его потрохами? И не правильно передаете, это строка, а строки должны заключаться в кавычки, у вас их нет.
И что должна сделать функция с этой html-строкой, отправить на сервер? И это при том, что у вас функция OpenAjax() не принимает никаких аргументов.
Помните я вам вопрос задавал - что лишнее?
У вас ссылки, они имеют url, они же по щелчку вызывают функцию. В самой функции этот url не используется, а функция хочет общаться с сервером асинхронно. Так зачем url? На кой ляд вообще вам тег А? А может функция не нужна, добрым надежным методом перегружаем страницы и все будет работать?
Я понимаю что мое исполнение кода далеко не совершенно
Ну так я вас по ушам тоже не бью  Вы больше потратите времени на поиски каких-то лоскутов с разных форумов, пытаясь сшить из них одеяло, чем если бы сели, задумались и попытались хотя выполнить пример что написал я, там и понимать то нечего.... ваши реальные запросы к ресурсу этих запчастей подставить, ваши переменные, добавить диалог (ошибки, пустой результат и т.п.) вот и все решение.
Последний раз редактировалось laimas, 19.02.2015 в 19:36.
|
|
|
|